#define _CRT_SECURE_NO_WARNINGS  1
#include<iostream>
#include<list>
#include "String.h"
#include "List.h"
#include<functional>
using namespace std;
//template<class ...Args>
//void Print(Args&&... args)
//{
//	cout << sizeof...(args) << endl;
//}
//int main()
//{
//	double x = 1.1;
//	Print();
//	Print(1);
//	Print(1, string("xxx"));
//	Print(1.1, string("xxx"), x);
//
//	return 0;
//}

//// 原理1：编译本质这里会结合引用折叠规则实例化出以下四个函数
//void Print();
//void Print(int&& arg1);
//void Print(int&& arg1, string&& arg2);
//void Print(double&& arg1, string&& arg2, double& arg3);
//// 原理2：更本质去看没有可变参数模板，我们实现出这样的多个函数模板才能支持
//// 这里的功能，有了可变参数模板，我们进一步被解放，他是类型泛化基础上叠加数量变化，让我们泛型编程更灵活。
//void Print();
//template <class T1>
//void Print(T1&& arg1);
//template <class T1, class T2>
//void Print(T1&& arg1, T2&& arg2);
//template <class T1, class T2, class T3>
//void Print(T1&& arg1, T2&& arg2, T3&& arg3);

//template<class ...Args>
//void Print(Args... args)
//{
//	// 下面是运行获取和解析，所以不支持这样用
//	cout << sizeof...(args) << endl;
//	for (size_t i = 0; i < sizeof...(args); i++)
//	{
//		cout << args[i] << " ";
//	}
//}

//void ShowList()
//{
//	// 编译时递归的终止条件，参数包是0个时，直接匹配这个函数
//	cout << endl;
//}
//template<class T,class ...Args>
//void ShowList(T x, Args... args)
//{
//	cout << x << " ";
//	// args是N个参数的参数包
//	// 调用ShowList，参数包的第一个传给x，剩下N-1传给第二个参数包
//	ShowList(args...);
//}
////编译时递归推导解析参数
//template<class ...Args>
//void Print(Args... args)
//{
//	ShowList(args...);
//}
//int main()
//{
//	Print();
//	Print(1);
//	Print(1,string("xxxxx"));
//	Print(1, string("xxxxx"), 2.2);
//
//	return 0;
//}

//template <class T, class ...Args>
//void ShowList(T x, Args... args)
//{
// cout << x << " ";
// Print(args...);
//}
// Print(1, string("xxxxx"), 2.2);调用时
// 本质编译器将可变参数模板通过模式的包扩展，编译器推导的以下三个重载函数函数
//void ShowList(double x)
//{
// cout << x << " ";
// ShowList();
//}
//
//void ShowList(string x, double z)
//{
// cout << x << " ";
// ShowList(z);
//}
//
//void ShowList(int x, string y, double z)
//{
// cout << x << " ";
// ShowList(y, z);
//}
//void Print(int x, string y, double z)
//{
// ShowList(x, y, z);
//}

//template<class T>
//const T& GetArg(const T& x)
//{
//	cout << x << endl;
//	return x;
//}
//template<class ...Args>
//void Arguments(Args... args)
//{ }
//template<class ...Args>
//void Print(Args... args)
//{
//	// 注意GetArg必须返回获得到的对象，这样才能组成参数包给Arguments
//	Arguments(GetArg(args)...);
//}
//int main()
//{
//	Print(1, 2.2, string("xxxxx"), 1.1);
//	return 0;
//}
//
//// 本质可以理解为编译器编译时，包的扩展模式
//// 将上面的函数模板扩展实例化为下面的函数
//// 是不是很抽象，C++11以后，只能说委员会的大佬设计语法思维跳跃得太厉害
//void Print(int x, double y, string z, double d)
//{
//	Arguments(GetArg(x), GetArg(y), GetArg(z), GetArg(d));
//}

//template <class... Args> void emplace_back(Args&&... args);
//template <class... Args> iterator emplace(const_iterator position,
//	Args&&... args);

//#include "String.h"
//#include "List.h"
//// emplace_back总体而言是更高效，推荐以后使用emplace系列替代insert和push系列
//int main()
//{
//	// 因为要创建哨兵位节点，所以构建了临时对象再拷贝构造了一个string对象
//	MY::list<MY::string> lt;
//	cout << "*********************************" << endl;
//	// 传左值，拷贝构造
//	MY::string s1("111");
//	lt.emplace_back(s1);
//	cout << "*********************************" << endl;
//
//	// 传右值，移动构造
//	lt.emplace_back(move(s1));
//	cout << "*********************************" << endl;
//
//	// 直接把构造string参数包往下传，直接用string参数包构造string
//	// 这里达到的效果是push_back做不到的
//	lt.emplace_back("111");
//	cout << "*********************************" << endl;
//
//	return 0;
//}

//#include "List.h"
//// emplace_back总体而言是更高效，推荐以后使用emplace系列替代insert和push系列
//int main()
//{
//	// 因为要创建哨兵位节点，所以构建了临时对象再拷贝构造了一个string对象
//	MY::list<pair<MY::string, int>> lt1;
//	cout << "*********************************" << endl;
//	// 跟push_back一样
//	// 构造pair + 拷贝/移动构造pair到list的节点中data上
//	pair<MY::string, int> kv("苹果", 1);
//	lt1.emplace_back(kv);
//	cout << "*********************************" << endl;
//	
//	lt1.emplace_back(move(kv));
//	cout << "*********************************" << endl;
//	
//	lt1.emplace_back("苹果", 1);
//	cout << "*********************************" << endl;
//	
//	// 最后调用s1和kv.first的析构函数，虽然它们之前被强转为右值并且被转移资源了，
//	// 但实际上它们还是左值，不会立马析构，等main函数执行完才会调用析构函数清理它们
//	return 0;
//}

//int main()
//{
//	MY::list<MY::string> lt;
//	cout << "*********************************" << endl;
//	// 传左值，拷贝构造
//	MY::string s1("111");
//	lt.emplace_back(s1);
//	cout << "*********************************" << endl;
//
//	// 传右值，移动构造
//	lt.emplace_back(move(s1));
//	cout << "*********************************" << endl;
//
//	// 直接把构造string参数包往下传，直接用string参数包构造string
//	// 这里达到的效果是push_back做不到的
//	lt.emplace_back("111");
//	cout << "*********************************" << endl;
//
//	MY::list<pair<MY::string, int>> lt1;
//	cout << "*********************************" << endl;
//	// 跟push_back一样
//	// 构造pair + 拷贝/移动构造pair到list的节点中data上
//	pair<MY::string, int> kv("苹果", 1);
//	lt1.emplace_back(kv);
//	cout << "*********************************" << endl;
//
//	lt1.emplace_back(move(kv));
//	cout << "*********************************" << endl;
//
//	lt1.emplace_back("苹果", 1);
//	cout << "*********************************" << endl;
//
//	// 最后调用s1和kv.first的析构函数，虽然它们之前被强转为右值并且被转移资源了，
//	// 但实际上它们还是左值，不会立马析构，等main函数执行完才会调用析构函数清理它们
//	return 0;
//}

//class Person
//{
//public:
//	Person(const char* name = "", int age = 0)
//		:_name(name)
//		, _age(age)
//	{
//	}
//	/*Person(const Person& p)
//		:_name(p._name)
//		,_age(p._age)
//	{}*/
//	/*Person& operator=(const Person& p)
//	{
//		if(this != &p)
//		{
//			_name = p._name;
//			_age = p._age;
//		}
//		return *this;
//	}*/
//	/*~Person()
//	{}*/
//private:
//	MY::string _name;
//	int _age;
//};
//int main()
//{
//	Person s1;
//	Person s2 = s1;
//	Person s3 = std::move(s1);
//	Person s4;
//	s4 = std::move(s2);
//	return 0;
//}

//class Person
//{
//public:
//	Person(const char* name = "", int age = 0)
//		:_name(name)
//		, _age(age)
//	{
//	}
//	Person(const Person& p)
//		:_name(p._name)
//		, _age(p._age)
//	{
//	}
//	Person& operator=(const Person& x) = default;
//	Person& operator=(Person&& x) = default;
//	Person(Person&& p) = default;
//	//Person(const Person& p) = delete;
//private:
//	MY::string _name;
//	int _age;
//};
//int main()
//{
//	Person s1;
//	Person s2 = s1;
//	Person s3 = std::move(s1);
//	Person s4;
//	s3 = s4;
//	Person s5;
//	s5 = move(s4);
//	return 0;
//}


//#include<functional>
//int f(int a, int b)
//{
//	return a + b;
//}
//struct Functor
//{
//public:
//	int operator()(int a, int b)
//	{
//		return a + b;
//	}
//};
//class Plus
//{
//public:
//	Plus(int n = 1)
//		:_n(n)
//	{ }
//	static int plusi(int a, int b)
//	{
//		return a + b;
//	}
//	double plusd(double a, double b)
//	{
//		return (a + b) * _n;
//	}
//private:
//	int _n;
//};
//int main()
//{
//	// 包装各种可调用对象
//	function<int(int, int)> f1 = f;
//	function<int(int, int)> f2 = Functor();
//	function<int(int, int)> f3 = [](int a, int b) {return a + b; };
//
//	cout << f1(1, 1) << endl;
//	cout << f2(2, 2) << endl;
//	cout << f3(3, 3) << endl;
//
//	// 包装静态成员函数
//	// 成员函数要指定类域并且前面加&才能获取地址,静态成员函数不需要
//	function<int(int, int)> f4 = Plus::plusi;
//	cout << f4(4, 4) << endl;
//
//	// 包装普通成员函数
//	// 普通成员函数还有一个隐含的this指针参数，所以绑定时传对象或者对象的指针过去都可以
//	function<double(Plus*, double, double)> f5 = &Plus::plusd;
//	Plus pd;
//	cout << f5(&pd, 1.1, 1.1) << endl;
//
//	function<double(Plus, double, double)> f6 = &Plus::plusd;
//	cout << f6(pd, 1.1, 1.1) << endl;
//	cout << f6(Plus(), 1.1, 1.1) << endl;
//
//	function<double(Plus&&, double, double)> f7 = &Plus::plusd;
//	cout << f7(move(pd), 1.1, 1.1) << endl;
//	cout << f7(Plus(), 1.1, 1.1) << endl;
//
//	return 0;
//}


//#include<functional>
//using placeholders::_1;
//using placeholders::_2;
//using placeholders::_3;
//
//int Sub(int a, int b)
//{
//	return (a - b) * 10;
//}
//int SubX(int a, int b, int c)
//{
//	return (a - b - c) * 10;
//}
//class Plus
//{
//public:
//	static int plusi(int a, int b)
//	{
//		return a + b;
//	}
//	double plusd(double a, double b)
//	{
//		return a + b;
//	}
//};
//int main()
//{
//	auto sub1 = bind(Sub, _1, _2);
//	cout << sub1(10, 5) << endl;
//
//	// bind 本质返回的一个仿函数对象
//	// 调整参数顺序（不常用）
//	// _1代表第一个实参
//	// _2代表第二个实参
//	auto sub2 = bind(Sub, _2, _1);
//	cout << sub2(10, 5) << endl;
//
//	// 调整参数个数（常用）
//	auto sub3 = bind(Sub, 100, _1);
//	cout << sub3(5) << endl;
//
//	auto sub4 = bind(Sub, _1, 100);
//	cout << sub4(5) << endl;
//
//	// 分别绑定第123个参数
//	auto sub5 = bind(SubX, 100, _1, _2);
//	cout << sub5(5, 1) << endl;
//
//	auto sub6 = bind(SubX, _1, 100, _2);
//	cout << sub6(5, 1) << endl;
//
//	auto sub7 = bind(SubX, _1, _2, 100);
//	cout << sub7(5, 1) << endl;
//
//	// 成员函数对象进行绑死，就不需要每次都传递了
//	function<double(Plus&&, double, double)> f6 = &Plus::plusd;
//	Plus pd;
//	cout << f6(move(pd), 1.1, 1.1) << endl;
//	cout << f6(Plus(), 1.1, 1.1) << endl;
//
//	// bind用于绑死一些固定参数
//	function<double(double, double)> f7 = bind(&Plus::plusd, Plus(), _1, _2);
//	cout << f7(1.1, 1.1) << endl;
//
//	return 0;
//}


#include<functional>
using placeholders::_1;
using placeholders::_2;
using placeholders::_3;
int main()
{
	//计算复利的lambda
	auto func1 = [](double rate, double money, int year)->double {
		double ret = money;
		for (int i = 0; i < year; i++)
		{
			ret += ret * rate;
		}
		return ret - money;
		};
	// 绑死一些参数，实现出支持不同年华利率，不同金额和不同年份计算出复利的结算利息
	function<double(double)> func3_1_5 = bind(func1, 0.015, _1, 3);
	function<double(double)> func5_1_5 = bind(func1, 0.015, _1, 5);
	function<double(double)> func10_2_5 = bind(func1, 0.025, _1, 10);
	function<double(double)> func20_3_5 = bind(func1, 0.035, _1, 30);

	cout << func3_1_5(1000000) << endl;
	cout << func5_1_5(1000000) << endl;
	cout << func10_2_5(1000000) << endl;
	cout << func20_3_5(1000000) << endl;

	return 0;
}